package com.xuecheng.media.service.impl;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.vod.model.v20170321.GetPlayInfoResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.media.dto.MediaDTO;
import com.xuecheng.api.media.qo.QueryMediaModel;
import com.xuecheng.api.content.teachplan.dto.TeachplanMediaDTO;
import com.xuecheng.api.media.vo.MediaAuidVo;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.enums.common.AuditEnum;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.media.agent.ContentApiAgent;
import com.xuecheng.media.common.constant.MediaErrorCode;
import com.xuecheng.media.common.utils.AliyunVODUtil;
import com.xuecheng.media.convert.MediaConvert;
import com.xuecheng.media.entity.Media;
import com.xuecheng.media.mapper.MediaMapper;
import com.xuecheng.media.service.MediaService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 媒资信息 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class MediaServiceImpl extends ServiceImpl<MediaMapper, Media> implements MediaService {

    @Autowired
    private ContentApiAgent contentApiAgent;


    @Value("${aliyun.region}")
    private String region;
    @Value("${aliyun.accessKeyId}")
    private String accessKeyId;
    @Value("${aliyun.accessKeySecret}")
    private String accessKeySecret;

    /**
     * 保存媒资数据
     * 1.判断关键数据
     * fieId filename type
     * 2.给信息数据赋值默认值
     * 添加没有业务数据
     * id companyId filename fileId
     * 2.把数据都添加到数据库中
     * 3.转换数据返回
     *
     * @param dto
     * @return
     */
    @Transactional
    public MediaDTO createMedia(MediaDTO dto) {
        //1.判断关键数据
        //     companyid  filename  fileid(videoId)
        if (StringUtil.isBlank(dto.getFileId())
                || StringUtil.isBlank(dto.getFilename())
                || ObjectUtils.isEmpty(dto.getCompanyId())

        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        //给数据赋值 默认值
        dto.setAuditStatus(AuditEnum.AUDIT_UNPAST_STATUS.getCode());
        //保存信息
        Media result = MediaConvert.INSTANCE.dto2entity(dto);
        boolean save = this.save(result);
        if (!save) {
            ExceptionCast.cast(MediaErrorCode.E_140001);
        }
        //将数据库最新数据返回
        Media po = this.getById(result.getId());
        MediaDTO resultDTO = MediaConvert.INSTANCE.entity2dto(po);


        return resultDTO;
    }


    /**
     * 分页查询
     *
     * @param params
     * @param model
     * @param aLong
     * @return
     */
    public PageVO<MediaDTO> queryCourseList(PageRequestParams params, QueryMediaModel model, Long aLong) {

        //1.判断业务数据 判断是否输入了负数 假如小于一就变成一
        if (params.getPageNo() < 1) {
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        }

        if (params.getPageSize() < 1) {
            params.setPageSize(PageRequestParams.DEFAULT_PAGE_SIZE);
        }

        LambdaQueryWrapper<Media> wrapper = new LambdaQueryWrapper<>();
        //2.判断条件查询数据 如果有数据在sql中添加条件
        if (StringUtil.isNotBlank(model.getFilename())) {
            wrapper.like(Media::getFilename, model.getFilename());
        }

        wrapper.eq(StringUtil.isNotBlank(model.getAuditStatus())
                    ,Media::getAuditStatus,model.getAuditStatus());

        if (StringUtil.isNotBlank(model.getType())) {
            wrapper.eq(Media::getType, model.getType());
        }


       wrapper.eq(!(ObjectUtils.isEmpty(aLong)),Media::getCompanyId, aLong);


        //3.创建分页数据
        Page<Media> page = new Page<>(params.getPageNo(), params.getPageSize());

        //4.根据分页和查询调价查询list数据
        Page<Media> basePage = this.page(page, wrapper);


        List<Media> records = basePage.getRecords();

        long total = basePage.getTotal();

        //4.1将po数据转换为dto
        List<MediaDTO> dtos = Collections.emptyList();

        if (!(ObjectUtils.isEmpty(records))) {

            dtos = MediaConvert.INSTANCE.entitys2dtos(records);
        }

        //5.将查询的结果放到PageVo里面
        /**
         * 1.当前页的集合数据
         * 2.数据库中的总条数
         * 3.当前页码
         * 4.每页条数
         */
        PageVO pageVO = new PageVO(dtos, total, params.getPageNo(), params.getPageSize());


        return pageVO;
    }

    /**
     * 预览媒资信息
     * 业务分析：
     * 1.判断关键数据
     * mediaId、companyId
     * 2.判断业务数据
     * 媒资信息
     * 判断是否存在（mediaId、companyId）
     * 判断媒资类型，如果是视频的话，要获得阿里云视频点播的播放地址
     * 3.获得媒资资源的路径地址Url
     * 获得最新的播放地址，从阿里云上获得
     * PS：优化--要从缓存中获得url（ps：缓存中必须存在url--1.创建media获得，2.服务端启动时来获得--定时任务）
     * 缓存中的url---设置缓存中的ttl
     * 4.返回结果内容
     *
     * @param mediaId
     * @param companyId
     * @return
     */
    public String previewMedia(Long mediaId, Long companyId) {

        // 1.判断关键数据
        // 	mediaId、companyId
        if (ObjectUtils.isEmpty(mediaId)
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        // 2.判断业务数据
        // 	媒资信息
        // 		判断是否存在（mediaId、companyId）
        // 		判断媒资类型，如果是视频的话，要获得阿里云视频点播的播放地址
        Media media = getById(mediaId);
        if (ObjectUtils.isEmpty(media)) {
            ExceptionCast.cast(CommonErrorCode.E_100104);
        }
        //如果公司id不为空  对其进行判断
        if (ObjectUtils.isEmpty(companyId)) {
            if (!(ObjectUtils.nullSafeEquals(media.getCompanyId(), companyId))) {
                ExceptionCast.cast(CommonErrorCode.E_100108);
            }
        }


        String playUrl = getplayUrl(media.getFileId());


        return playUrl;
    }


    /**
     * 获取planurl
     *
     * @param fileId
     * @return
     */
    private String getplayUrl(String fileId) {


        String playUrl = "";

        try {
            DefaultAcsClient client =
                    AliyunVODUtil.initVodClient(region, accessKeyId, accessKeySecret);

            GetPlayInfoResponse response = AliyunVODUtil.getPlayInfo(client, fileId);

            List<GetPlayInfoResponse.PlayInfo> playInfoList = response.getPlayInfoList();

            if (!(ObjectUtils.isEmpty(playInfoList))) {
                GetPlayInfoResponse.PlayInfo playInfo = playInfoList.get(0);
                playUrl = playInfo.getPlayURL();
            }

        } catch (Exception e) {
            ExceptionCast.cast(MediaErrorCode.E_140014);
        }
        return playUrl;

    }


    /**
     * 删除媒资信息功能
     * 业务分析：
     * 1.判断关键数据
     * mediaId、companyId
     * 2.判断业务数据
     * 媒资信息
     * 判断是否存在
     * 判断审核状态：只有审核通过不能删除
     * 判断媒资信息是否有绑定课程计划数据
     * 绑定媒资和课程计划数据：content（发送feign）
     * teachplan_media
     * 3.删除媒资信息
     * 媒资服务中的数据：Media
     * 阿里云对应的视频
     *
     * @param mediaId
     * @param companyId
     */
    @Transactional
    public void removeMediaById(Long mediaId, Long companyId) {


        //	1.判断关键数据
        //		mediaId、companyId
        if (ObjectUtils.isEmpty(mediaId)||
                ObjectUtils.isEmpty(companyId)
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        //	2.判断业务数据
        //		媒资信息
        //			判断是否存在
        //			判断审核状态：只有审核通过不能删除
        Media media = this.getById(mediaId);
        if (ObjectUtils.isEmpty(media)) {
            ExceptionCast.cast(MediaErrorCode.E_140005);
        }
        String auditStatus = media.getAuditStatus();
        if (ObjectUtils.nullSafeEquals(auditStatus, AuditEnum.AUDIT_PASTED_STATUS.getCode())) {

            ExceptionCast.cast(MediaErrorCode.E_140008);

        }

        //			判断媒资信息是否有绑定课程计划数据
        //				绑定媒资和课程计划数据：content（发送feign）
        //											   teachplan_media
        RestResponse<TeachplanMediaDTO> restResponse = contentApiAgent.getMediaById(mediaId);


        if (!(restResponse.isSuccessful())) {
            ExceptionCast.castWithCodeAndDesc(restResponse.getCode(), restResponse.getMsg());
        }

        //判断teachplanmedia表有没有绑定
        TeachplanMediaDTO teachplanMediaDTO = restResponse.getResult();

        /*if (!(ObjectUtils.nullSafeEquals(teachplanMediaDTO.getMediaId(), mediaId))) {
            ExceptionCast.cast(CommonErrorCode.E_100108);
        }
*/

        if (!ObjectUtils.isEmpty(teachplanMediaDTO)) {
            ExceptionCast.cast(MediaErrorCode.E_140002);
        }
        //3.删除媒资信息
        //媒资服务中的数据：Media
        //阿里云对应的视频
        boolean remove = this.removeById(mediaId);
        try {
            String fileId = media.getFileId();
            DefaultAcsClient client =
                    AliyunVODUtil.initVodClient(region, accessKeyId, accessKeySecret);
            AliyunVODUtil.deleteVideo(client, fileId);
            if (!remove) {
                ExceptionCast.cast(MediaErrorCode.E_140002);
            }
        } catch (Exception e) {
            String message = e.getMessage();
            log.error(MediaErrorCode.E_140002 + " : {}", message);
            ExceptionCast.cast(MediaErrorCode.E_140002);
        }


    }

    /** 运营媒资分页查询
     *
     * @param params
     * @param model
     * @return
     */
    public PageVO queryMediaMList(PageRequestParams params, QueryMediaModel model) {

        //1.判断业务数据 判断是否输入了负数 假如小于一就变成一
        if (params.getPageNo() < 1) {
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        }

        if (params.getPageSize() < 1) {
            params.setPageSize(PageRequestParams.DEFAULT_PAGE_SIZE);
        }

        LambdaQueryWrapper<Media> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Media::getStatus,CommonEnum.USING_FLAG.getCode());
        //2.判断条件查询数据 如果有数据在sql中添加条件
        if (StringUtil.isNotBlank(model.getFilename())) {
            wrapper.like(Media::getFilename, model.getFilename());
        }

        if (StringUtil.isNotBlank(model.getType())) {
            wrapper.eq(Media::getType, model.getType());
        }



        //3.创建分页数据
        Page<Media> page = new Page<>(params.getPageNo(), params.getPageSize());

        //4.根据分页和查询调价查询list数据
        Page<Media> basePage = this.page(page, wrapper);


        List<Media> records = basePage.getRecords();

        long total = basePage.getTotal();

        //4.1将po数据转换为dto
        List<MediaDTO> dtos = Collections.emptyList();

        if (!(ObjectUtils.isEmpty(records))) {

            dtos = MediaConvert.INSTANCE.entitys2dtos(records);
        }

        //5.将查询的结果放到PageVo里面
        /**
         * 1.当前页的集合数据
         * 2.数据库中的总条数
         * 3.当前页码
         * 4.每页条数
         */
        PageVO pageVO = new PageVO(dtos, total, params.getPageNo(), params.getPageSize());


        return pageVO;

    }

    /**媒资审核运营
     *
     * @param dto
     */
    @Transactional
    public void approveMedia(MediaDTO dto) {
        //     1.判断关键数据
        //    auditMind  auditStatus  courseid
        if (StringUtil.isBlank(dto.getAuditMind()) ||
                StringUtil.isBlank(dto.getAuditStatus())
                || ObjectUtils.isEmpty(dto.getId()))
        {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        //2.判断业务数据
        //    课程基础信息
        //        判断是否存在
        //        判断是否删除
        //        判断审核状态]
        //            必须为：已提交
        //如果课程处于 '审核通过' 是不能进行课程审核的。
        LambdaQueryWrapper<Media> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Media::getId, dto.getId());
        queryWrapper.eq(Media::getStatus, CommonEnum.USING_FLAG.getCode());
        queryWrapper.eq(Media::getAuditStatus,AuditEnum.AUDIT_UNPAST_STATUS .getCode());

        int count = this.count(queryWrapper);

        if (count < 1) {
            ExceptionCast.cast(MediaErrorCode.E_140004);
        }


        //    审核状态
        //        运营平台只能给课程审核状态赋值：审核通过、审核未通过

        //3.修改课程审核信息
        //    auditMind  auditStatus  auditNum（每次+1）

        LambdaUpdateWrapper<Media> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Media::getAuditMind,dto.getAuditMind())
                .set(Media::getAuditStatus,dto.getAuditStatus())
                //.set(CourseBase::getAuditNums,dto.getAuditNums())
                .set(Media::getChangeDate, LocalDateTime.now())
                .eq(Media::getId,dto.getId());

        boolean result = this.update(updateWrapper);

        if (!result) {
            ExceptionCast.cast(MediaErrorCode.E_140009);
        }

    }


    /**
     * 预览媒资视频运营
     * @param mediaId
     * @return
     */
    public String previewMediaOperation(Long mediaId) {

        // 1.判断关键数据
        // 	mediaId
        if (ObjectUtils.isEmpty(mediaId)
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        // 2.判断业务数据
        // 	媒资信息
        // 		判断是否存在（mediaId）
        // 		判断媒资类型，如果是视频的话，要获得阿里云视频点播的播放地址
        Media media = getById(mediaId);
        if (ObjectUtils.isEmpty(media)) {
            ExceptionCast.cast(CommonErrorCode.E_100104);
        }


        String playUrl = getplayUrl(media.getFileId());


        return playUrl;
    }


    //媒资信息查询
    public RestResponse<MediaDTO> getById4Service(Long mediaId) {
        if (ObjectUtils.isEmpty(mediaId)) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        Media byId = this.getById(mediaId);
        if (ObjectUtils.isEmpty(byId)) {
            return RestResponse.validfail(MediaErrorCode.E_140005);
        } else {
            MediaDTO dto = MediaConvert.INSTANCE.entity2dto(byId);
           return RestResponse.success(dto);
        }


    }


}
